package thread;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author SWJ
 * @create 2021-06-24 14:05
 * 熟悉自定义注解测试自定义注解相关规则
 */
public class TestAnnotation {
}

/**
 * 0.首先注意：自定义注解语法与java不同，不要套用java格式
 * 1.定义自定义注解
 * 1.注解定义要使用“@interface注解名的方式来定义”
 * 1.1需要通过@Target注解来描述当前自定义注解可以使用的位置
 * <p>
 * 注意@Target注解需要导包，
 * 它的值通过“ElementType.METHOD”静态常量来指定
 * 如果需要指定多个值，可以使用{ , }的格式来写
 */
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD})

/**1.2通过@Retention注解表面此定义注解的生命周期
 * 注意：@Retention使用时候也需要导包
 * 它的值通过“RetentionPolicy.”静态常量来指定
 *也就是自定义注解可以存活多久：源文件中/字节码文件中/运行时
 * 而且，这三个值只能选一个，不能写多个
 * */
@Retention(RetentionPolicy.SOURCE)
//定义自定义注解，注解名是Test,并指定此注解作用的位置
        /*0.首先注意:自定义注解的语法与java不同,不要套用java的格式*/
//1.定义自定义主解,注解名是Test,并通过两个元注解表示此注解的作用位置和生命周期
        /*1.注解定义要使用"@interface 注解名"的方式来定义*/
@interface Test {
    /**
     * 自定义注解可以添加功能--给自定义注解添加属性
     * 注意:int age();不是方法的定义，而是自定义注解
     * age属性的语法
     * 如果为了方便，还可以给属性
     * 如果为了使用注解时方便,还可以给属性指定默认值,
     * 这样就可以直接使用,格式:int age() default 0;
     */
    int age() default 0;

    /**
     * 4.注解中还可以添加功能-可以定义特殊属性value
     * 特殊属性的定义方式与别的属性相同,主要是使用方式不同
     * 使用此注解给属性赋值的时候,可以不用写成"@Test(value = "Apple")",
     * 格式可以简化"@Test("Apple")"直接写值
     * 但是自定义注解类中的赋予默认值不可以简写,
     * 如果自定义了默认值,可以不用赋值,直接使用
     */

    String value() default "apple";
}

/**
 * 2.定义一个类来测试自定义注解
 * 2.使用注解时只要自定义注解名字前加@即可使用此注解
 */
//@Test
class TestAbnno {
    /**
     * 测试分别给TestAbnno类/name属性eat方法都添加@Test
     * 只有方法上不报错
     * 结论：自定义注解能够加载什么位置，取决于@Target注解的值
     * <p>
     * 测试2修改@Target注解的值
     * Target({ElementType.METHOD,ElementType.TYPE,
     * ElementType.FIELD})
     * <p>
     * 结论：注解@Test可以存在于多个位置，如果有多个值，格式{,}
     * 原因：Target注解的源码：ElementType[]value();
     * 元素类型方法 类型 字段
     * 原因:Target注解的源码:ElementType[] value();
     */
//    @Test
    String name;

    /**
     * 测试3：当我们添加了注解的age属性后，@Test注解报错
     * 结论：当没有给自定义注解定义属性时，可以直接使用但是如果有属性了，必须给属性赋值
     * 测试4：给@Test注解的属性赋值以后，就不报错了
     * 结论：给属性赋值的格式“ @Test(age = 18)”，注意不能直接写值，这是错误的格式
     * 测试5:给age属性赋予默认值后,可以不加属性值,直接使用注解,
     * 此时使用的就是age的默认值
     */

    //    @Test(age = 18)
    public void eat() {
        System.out.println("222222");

    }

}